#if UNITY_EDITOR
using DBService.ExternalContent;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEngine;

/// <summary>
/// Addressable组构建编辑器窗口，提供可视化界面管理Addressable资源组构建
/// </summary>
public class BuildTool : EditorWindow
{
    private AddressableAssetSettings _addressableSettings, defaultSettings;
    private List<AddressableAssetGroup> _allGroups = new();
    private Dictionary<string, bool> _groupSelection = new();
    private Vector2 _scrollPosition;
    private string _searchText = "";
    private bool _isBuilding = false;
    private BuildTarget _selectedTarget;

    private const string LogFilePath = "Library/AddressableBuildLogs.txt";

    /// <summary>
    /// 显示编辑器窗口
    /// </summary>
    [MenuItem("DBService/选择寻址组_构建")]
    public static void ShowWindow()
    {
        GetWindow<BuildTool>("Addressable Group Builder");
    }

    private void OnEnable()
    {
        RefreshAddressableSettings();
    }

    /// <summary>
    /// 组分类信息，用于按来源路径分组显示
    /// </summary>
    private class GroupCategory
    {
        public string Name { get; set; }
        public string Path { get; set; }
        public List<AddressableAssetGroup> Groups { get; set; } = new();
        public bool Expanded { get; set; } = true;
    }

    private List<GroupCategory> _groupCategories = new();

    private void RefreshAddressableSettings()
    {
        defaultSettings = _addressableSettings = AddressableAssetSettingsDefaultObject.Settings;

        if (_addressableSettings != null)
        {
            _allGroups = _addressableSettings.groups
                .Where(g => g != null)
                .ToList();

            // 按名称自然排序
            _allGroups = NaturalSort(_allGroups, g => g.Name);

            _groupSelection.Clear();
            foreach (var group in _allGroups)
            {
                bool saved = EditorPrefs.GetBool($"BuildTool_Group_{group.Guid}", false);
                _groupSelection[group.Guid] = saved;
            }

            // 重新分类组
            CategorizeGroups();
        }

        _selectedTarget = EditorUserBuildSettings.activeBuildTarget;
    }

    /// <summary>
    /// 将组按来源路径分类
    /// </summary>
    private void CategorizeGroups()
    {
        _groupCategories.Clear();

        // 创建分类字典
        var categoryDict = new Dictionary<string, GroupCategory>();

        foreach (var group in _allGroups)
        {
            // 获取组所属的AddressableAssetSettings路径
            string groupPath = GetGroupSourcePath(group);
            string categoryName = GetCategoryName(groupPath);

            if (!categoryDict.ContainsKey(categoryName))
            {
                categoryDict[categoryName] = new GroupCategory
                {
                    Name = categoryName,
                    Path = groupPath
                };
            }

            categoryDict[categoryName].Groups.Add(group);
        }

        // 转换为列表并排序
        _groupCategories = categoryDict.Values
            .OrderBy(c => GetCategorySortOrder(c.Name))
            .ThenBy(c => c.Name)
            .ToList();

        // 对每个分类中的组进行自然排序
        foreach (var category in _groupCategories)
        {
            category.Groups = NaturalSort(category.Groups, g => g.Name);
        }
    }

    /// <summary>
    /// 获取组的来源路径
    /// </summary>
    private string GetGroupSourcePath(AddressableAssetGroup group)
    {
        try
        {
            // 通过AssetDatabase获取组本身的路径
            string groupPath = AssetDatabase.GetAssetPath(group);

            if (string.IsNullOrEmpty(groupPath))
                return "Unknown";

            // 判断路径类型
            if (groupPath.StartsWith("Assets/"))
                return "Main Project";
            else if (groupPath.Contains("Packages/"))
                return ExtractPackageName(groupPath);
            else
                return "Other";
        }
        catch (System.Exception ex)
        {
            Debug.LogWarning($"获取组 {group.Name} 路径失败: {ex.Message}");
            return "Unknown";
        }
    }

    /// <summary>
    /// 从路径中提取包名
    /// </summary>
    private string ExtractPackageName(string path)
    {
        if (path.Contains("Packages/"))
        {
            int startIndex = path.IndexOf("Packages/") + 9; // "Packages/".Length
            int endIndex = path.IndexOf('/', startIndex);
            if (endIndex > startIndex)
            {
                string packageName = path.Substring(startIndex, endIndex - startIndex);

                // 处理包名显示
                if (packageName.StartsWith("com.") || packageName.StartsWith("org."))
                {
                    return packageName;
                }
                return packageName;
            }
            return "Package";
        }
        return "Package";
    }

    /// <summary>
    /// 获取分类显示名称
    /// </summary>
    private string GetCategoryName(string path)
    {
        return path switch
        {
            "Main Project" => "主工程",
            "Unknown" => "未知来源",
            "Other" => "其他",
            _ => $"包: {path}"
        };
    }

    /// <summary>
    /// 获取分类排序优先级
    /// </summary>
    private int GetCategorySortOrder(string categoryName)
    {
        return categoryName switch
        {
            "主工程" => 0,
            "未知来源" => 999,
            "其他" => 998,
            _ when categoryName.StartsWith("包:") => 1,
            _ => 997
        };
    }

    private void OnGUI()
    {
        EditorGUILayout.LabelField("Addressable 组构建工具", EditorStyles.boldLabel);
        EditorGUILayout.Space();

        // 刷新按钮
        if (GUILayout.Button("刷新组列表", GUILayout.Height(20)))
        {
            RefreshAddressableSettings();
        }

        EditorGUILayout.Space();

        // 搜索框
        EditorGUILayout.BeginHorizontal();
        _searchText = EditorGUILayout.TextField("搜索组：", _searchText);
        if (GUILayout.Button("清空", GUILayout.Width(50)))
        {
            _searchText = "";
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        // 组列表 - 按分类显示
        EditorGUILayout.LabelField("选择要构建的组：", EditorStyles.label);

        if (_groupCategories.Count == 0)
        {
            EditorGUILayout.HelpBox("没有找到任何Addressable组。", MessageType.Info);
        }
        else
        {
            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, GUILayout.Height(500));

            // 显示分类
            foreach (var category in _groupCategories)
            {
                // 过滤搜索
                var filteredGroups = category.Groups;
                if (!string.IsNullOrEmpty(_searchText))
                {
                    filteredGroups = category.Groups
                        .Where(g => g.Name.ToLower().Contains(_searchText.ToLower()))
                        .ToList();
                }

                if (filteredGroups.Count == 0)
                    continue;

                // 分类标题
                EditorGUILayout.BeginVertical(GUI.skin.box);

                // 折叠/展开按钮
                EditorGUILayout.BeginHorizontal();
                category.Expanded = EditorGUILayout.Foldout(category.Expanded, $"{category.Name} ({filteredGroups.Count} 个组)", true);

                // 分类操作按钮
                if (GUILayout.Button("全选", GUILayout.Width(50)))
                {
                    foreach (var group in category.Groups)
                        _groupSelection[group.Guid] = true;
                }
                if (GUILayout.Button("全不选", GUILayout.Width(50)))
                {
                    foreach (var group in category.Groups)
                        _groupSelection[group.Guid] = false;
                }

                EditorGUILayout.EndHorizontal();

                // 显示组列表
                if (category.Expanded)
                {
                    foreach (var group in filteredGroups)
                    {
                        EditorGUILayout.BeginHorizontal();
                        GUI.color = _groupSelection[group.Guid] ? Color.green : Color.white;

                        _groupSelection[group.Guid] = EditorGUILayout.ToggleLeft(
                            $"{group.Name} ({group.entries.Count} 个资源)",
                            _groupSelection[group.Guid]
                        );

                        GUI.color = Color.white;

                        EditorGUILayout.LabelField($"[{GetGroupTypeString(group)}]",
                            GUILayout.Width(100));
                        EditorGUILayout.EndHorizontal();
                    }
                }

                EditorGUILayout.EndVertical();
                EditorGUILayout.Space();
            }

            EditorGUILayout.EndScrollView();
        }

        // 选择按钮组
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("全选"))
        {
            foreach (var g in _allGroups) _groupSelection[g.Guid] = true;
        }
        if (GUILayout.Button("全不选"))
        {
            foreach (var g in _allGroups) _groupSelection[g.Guid] = false;
        }
        if (GUILayout.Button("选中搜索的组"))
        {
            SelectSearchedGroups(true);
        }
        if (GUILayout.Button("取消搜索的组"))
        {
            SelectSearchedGroups(false);
        }
        EditorGUILayout.EndHorizontal();

        // 已选中计数
        int selectedCount = _groupSelection.Values.Count(v => v);
        EditorGUILayout.LabelField($"已选中：{selectedCount}/{_allGroups.Count} 个组");

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("构建设置", EditorStyles.boldLabel);

        // 构建平台
        _selectedTarget = (BuildTarget)EditorGUILayout.EnumPopup("构建平台：", _selectedTarget);

        EditorGUILayout.Space();

        // 构建按钮
        GUI.enabled = !_isBuilding && selectedCount > 0;
        if (GUILayout.Button(_isBuilding ? "构建中..." : "构建选中的组", GUILayout.Height(35)))
        {
            BuildSelectedGroups();
        }
        GUI.enabled = true;

        if (_isBuilding)
        {
            EditorGUILayout.HelpBox("构建进行中，请等待...", MessageType.Info);
        }
    }

    private string GetGroupTypeString(AddressableAssetGroup group)
    {
        if (group.HasSchema<BundledAssetGroupSchema>()) return "Bundled";
        if (group.HasSchema<PlayerDataGroupSchema>()) return "PlayerData";
        return "Default";
    }

    /// <summary>
    /// 选中或取消选中搜索的组
    /// </summary>
    private void SelectSearchedGroups(bool select)
    {
        foreach (var group in _allGroups)
        {
            // 如果没有搜索文本，则处理所有组
            if (string.IsNullOrEmpty(_searchText) ||
                group.Name.ToLower().Contains(_searchText.ToLower()))
            {
                _groupSelection[group.Guid] = select;
            }
        }
    }

    // 自然排序方法
    private List<T> NaturalSort<T>(List<T> list, System.Func<T, string> nameSelector)
    {
        return list
            .OrderBy(item => nameSelector(item), new NaturalComparer())
            .ToList();
    }

    /// <summary>
    /// 自然排序比较器（支持数字序号排序）
    /// </summary>
    /// <example>"组2" 会排在 "组11" 前面</example>
    private class NaturalComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            if (x == null && y == null) return 0;
            if (x == null) return -1;
            if (y == null) return 1;

            int i = 0, j = 0;

            while (i < x.Length && j < y.Length)
            {
                if (char.IsDigit(x[i]) && char.IsDigit(y[j]))
                {
                    // 提取数字部分
                    string num1 = ExtractNumber(x, ref i);
                    string num2 = ExtractNumber(y, ref j);

                    // 比较数字
                    int result = CompareNumbers(num1, num2);
                    if (result != 0) return result;
                }
                else
                {
                    // 比较字符
                    if (x[i] != y[j])
                        return x[i].CompareTo(y[j]);

                    i++;
                    j++;
                }
            }

            return x.Length.CompareTo(y.Length);
        }

        private string ExtractNumber(string s, ref int index)
        {
            int start = index;
            while (index < s.Length && char.IsDigit(s[index]))
                index++;

            return s.Substring(start, index - start);
        }

        private int CompareNumbers(string num1, string num2)
        {
            // 如果数字长度不同，先比较长度
            if (num1.Length != num2.Length)
                return num1.Length.CompareTo(num2.Length);

            // 长度相同，逐位比较
            for (int i = 0; i < num1.Length; i++)
            {
                if (num1[i] != num2[i])
                    return num1[i].CompareTo(num2[i]);
            }

            return 0;
        }
    }

    private void BuildSelectedGroups()
    {
        var selectedGroups = _allGroups.Where(g => _groupSelection[g.Guid]).ToList();

        if (selectedGroups.Count == 0)
        {
            EditorUtility.DisplayDialog("提示", "请至少选择一个组进行构建。", "确定");
            return;
        }

        _isBuilding = true;
        Repaint();

        // 保存选择状态
        foreach (var kvp in _groupSelection)
            EditorPrefs.SetBool($"BuildTool_Group_{kvp.Key}", kvp.Value);

        try
        {
            // 暂存 IncludeInBuild 状态
            var originalStates = new Dictionary<AddressableAssetGroup, bool>();
            foreach (var group in _allGroups)
            {
                var schema = group.GetSchema<BundledAssetGroupSchema>();
                if (schema != null)
                {
                    originalStates[group] = schema.IncludeInBuild;
                    schema.IncludeInBuild = _groupSelection[group.Guid];
                }
            }

            Log($"开始构建 {selectedGroups.Count} 个组...");

            // 使用Addressables的构建API
            bool buildSuccess = BuildAddressablesContent();

            // 恢复 Include 状态
            foreach (var kvp in originalStates)
            {
                var schema = kvp.Key.GetSchema<BundledAssetGroupSchema>();
                if (schema != null)
                    schema.IncludeInBuild = kvp.Value;
            }

            if (buildSuccess)
            {
                Log($"成功构建 {selectedGroups.Count} 个组！");
                EditorUtility.DisplayDialog("成功", $"成功构建 {selectedGroups.Count} 个组！", "确定");
            }
            else
            {
                EditorUtility.DisplayDialog("失败", "构建失败，请查看控制台日志获取详细信息。", "确定");
            }
        }
        catch (System.Exception ex)
        {
            Log($"构建异常: {ex.Message}\n{ex.StackTrace}");
            EditorUtility.DisplayDialog("异常", $"构建过程中发生异常：{ex.Message}", "确定");
        }
        finally
        {
            _isBuilding = false;
            Repaint();
        }
    }

    private bool BuildAddressablesContent()
    {
        try
        {
            // 使用正确的构建方法签名和结果类型
            AddressableAssetSettings.BuildPlayerContent(out AddressablesPlayerBuildResult result);

            if (result != null)
            {
                // 检查构建结果
                if (string.IsNullOrEmpty(result.Error))
                {
                    Log($"Addressables 构建成功完成 - 耗时: {result.Duration:F2}秒, 位置数量: {result.LocationCount}");
                    return true;
                }
                else
                {
                    Log($"Addressables 构建失败: {result.Error}");
                    return false;
                }
            }
            else
            {
                Log("构建结果为空，构建可能失败");
                return false;
            }
        }
        catch (System.Exception ex)
        {
            Log($"构建过程中发生异常: {ex.Message}\n{ex.StackTrace}");
            return false;
        }
    }

    /// <summary>
    /// 记录构建日志到文件和控制台
    /// </summary>
    /// <param name="message">日志内容</param>
    private void Log(string message)
    {
        string log = $"[{System.DateTime.Now:HH:mm:ss}] {message}\n";
        Debug.Log($"[BuildTool] {message}");

        try
        {
            File.AppendAllText(LogFilePath, log);
        }
        catch (System.Exception ex)
        {
            Debug.LogWarning($"[BuildTool] 无法写入日志文件: {ex.Message}");
        }
    }
}
#endif